package com.chenxin.wms.process.task.impl;

import com.chenxin.common.annotation.WmsLogs;
import com.chenxin.common.core.domain.ProcResult;
import com.chenxin.common.enums.wms.IbDetailStatus;
import com.chenxin.common.enums.wms.TaskStatus;
import com.chenxin.common.enums.wms.TaskType;
import com.chenxin.common.enums.wms.ZoneType;
import com.chenxin.common.utils.StringUtils;
import com.chenxin.wms.domain.*;
import com.chenxin.wms.domain.po.LocationInfo;
import com.chenxin.wms.mapper.*;
import com.chenxin.wms.process.inbound.IProcIbMasterStatusUpdate;
import com.chenxin.wms.process.task.IProcTaskCancelById;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;

@Service
public class ProcTaskCancelByIdImpl implements IProcTaskCancelById {
    @Autowired
    private TaskMapper taskMapper;
    @Autowired
    private StockMapper stockMapper;
    @Autowired
    private LocationMapper locationMapper;
    @Autowired
    private IbMasterMapper ibMasterMapper;
    @Autowired
    private IbDetailMapper ibDetailMapper;
    @Autowired
    private ObMasterMapper obMasterMapper;
    @Autowired
    private ObDetailMapper obDetailMapper;
    @Autowired
    private IProcIbMasterStatusUpdate ibMasterStatusUpdate;

    @WmsLogs(name = "任务取消")
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    @Override
    public ProcResult call(Long taskId, Long creator) {
        // 待取消的任务ID不能为空
        if (StringUtils.isNull(taskId)) {
            return ProcResult.error("task_cancel_err#001", "待取消的任务ID不能为空");
        }
        // 根据ID获取任务详情
        TaskEntity taskByCancel = taskMapper.selectById(taskId);
        if (taskByCancel == null) {
            return ProcResult.error("task_cancel_err#002", "任务ID【" + taskId + "】不存在");
        }
        // 优先判断哪些任务数据不能取消（位置变动不能取消，特殊场景任务无法取消-可补充）
        String fromPosition = taskByCancel.getFromPosition();
        String curPosition = taskByCancel.getCurPosition();
        if (!fromPosition.equals(curPosition)) {
            return ProcResult.error("task_cancel_err#003", "任务【" + taskId + "】当前位置【" + curPosition + "】已发生位置变动，无法取消");
        }
        // 根据起始位置获取位置相关信息
        LocationInfo fromPositionInfo = locationMapper.selectLocationByNo(fromPosition);
        if (fromPositionInfo == null) {
            return ProcResult.error("task_cancel_err#004", "任务【" + taskId + "】的起始位置【" + fromPosition + "】在货位表中不存在");
        }
        // 获取关联库存
        Long stockId = taskByCancel.getStockId();
        StockEntity sourceStock = stockMapper.selectById(stockId);
        if (sourceStock == null) {
            return ProcResult.error("task_cancel_err#005", "任务【" + taskId + "】的关联库存【" + stockId + "】不存在");
        }
        // 获取任务的状态以及任务类型&子类型
        String zoneType = fromPositionInfo.getZoneType();
        Integer taskStatus = taskByCancel.getTaskStatus();
        String taskType = taskByCancel.getTaskType();
        String taskSubType = taskByCancel.getTaskSubType();
        Long masterId = taskByCancel.getMasterId();
        Long detailId = taskByCancel.getDetailId();
        Date workDate = new Date();

        if (ZoneType.AUTO.getCode().equals(zoneType) && taskStatus > TaskStatus.INIT.getCode()) {
            return ProcResult.error("task_cancel_err#005", "任务【" + taskId + "】已执行，无法取消");
        }
        // 根据不同的任务类型进行不同的取消流程
        if (TaskType.RECEIVE_IN.getCode().equals(taskType)) {
            // 入库任务取消（任务、库存、入库单据）
            IbDetailEntity ibDetail = ibDetailMapper.selectById(detailId);
            if (ibDetail == null) {
                return ProcResult.error("task_cancel_err#006", "任务【" + taskId + "】的入库明细不存在,无法取消");
            }
            // 匹配相关入库单据
            IbMasterEntity ibMaster = ibMasterMapper.selectById(masterId);
            if (ibMaster == null) {
                return ProcResult.error("task_cancel_err#007", "任务【" + taskId + "】的入库单据不存在,无法取消");
            }
            // 库存扣减（如果收货库存为累加收货，则仅扣除对应数量的库存）
            stockMapper.deleteById(stockId);
            // 单据数量返还（状态同步更新）
            BigDecimal actualQty = ibDetail.getIbActualQty().subtract(sourceStock.getStockQty());
            ibDetail.setIbActualQty(actualQty);
            if (actualQty.compareTo(BigDecimal.ZERO) > 0) {
                ibDetail.setIbDetailStatus(IbDetailStatus.EXEC.getCode());
            } else {
                ibDetail.setIbDetailStatus(IbDetailStatus.INIT.getCode());
            }
            ibDetail.setUpdater(creator);
            ibDetail.setUpdateDate(workDate);
            int rows = ibDetailMapper.updateById(ibDetail);
            if (rows == 0) {
                return ProcResult.error("task_cancel_err#008", "任务【" + taskId + "】的入库明细【" + detailId + "】更新失败");
            }
            ibMaster.setUpdater(creator);
            ibMaster.setUpdateDate(workDate);
            ibMasterMapper.updateById(ibMaster);
            ibMasterStatusUpdate.statusUpdateByMasterId(masterId, creator);
        } else if (TaskType.SHIPMENT_OUT.getCode().equals(taskType)) {
            // 出库任务取消（任务、库存、出库单据）
            ObMasterEntity obMaster = obMasterMapper.selectById(masterId);
            if (obMaster == null) {
                return ProcResult.error("task_cancel_err#009", "任务【" + taskId + "】的出库单据不存在,无法取消");
            }

            ObDetailEntity obDetail = obDetailMapper.selectById(detailId);
            if (obDetail == null) {
                return ProcResult.error("task_cancel_err#010", "任务【" + taskId + "】的出库明细不存在,无法取消");
            }

        } else if (TaskType.CHECK.getCode().equals(taskType)) {
            // 盘点任务取消（任务、库存）

        } else if (TaskType.STOCK_MOVE.getCode().equals(taskType)) {
            // 位移任务取消（任务、库存）

        } else {
            return ProcResult.error("task_cancel_err#002", "任务类型【" + taskType + "】不支持取消");
        }
        // 更新任务状态
        taskByCancel.setTaskStatus(TaskStatus.CANCEL.getCode());
        taskByCancel.setComments("任务被人为取消!");
        taskByCancel.setUpdater(creator);
        taskByCancel.setUpdateDate(workDate);
        taskMapper.updateById(taskByCancel);
        return ProcResult.success("成功取消任务【" + taskId + "】");
    }
}
